package com.yiquan.chat.service;

import java.util.*;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.persistence.criteria.Selection;

import com.yiquan.chat.client.UserClient;
import com.yiquan.chat.dao.MessageDao;
import com.yiquan.chat.netty.UserChannelRel;
import com.yiquan.chat.pojo.Message;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import util.IdWorker;

import com.yiquan.chat.dao.ConverseDao;
import com.yiquan.chat.pojo.Converse;

/**
 * 服务层
 *
 * @author Administrator
 */
@Service
public class ConverseService {

    @Autowired
    private ConverseDao converseDao;

    @Autowired
    private MessageDao messageDao;

    @Autowired
    private IdWorker idWorker;

    @Autowired
    private UserClient userClient;

    @Autowired
    private MessageService messageService;

    public static final Integer CONVERSE_NORMAL = 0;

    public static final Integer CONVERSE_DELETE = 1;

    @Autowired
    private RedisTemplate redisTemplate;

    private static final String CHAT_MODULE_ID = "CHAT_MODULE_ID";


    /**
     * 获取用户id (20000000-29999999)
     *
     * @return
     */
    public Long getUniqueId() {
        redisTemplate.opsForValue().setIfAbsent(CHAT_MODULE_ID, 20000000L);
        Long temporaryUserId = redisTemplate.opsForValue().increment(CHAT_MODULE_ID);
        return temporaryUserId;
    }


    /**
     * 查询全部列表
     *
     * @return
     */
    public List<Converse> findAll() {
        return converseDao.findAll();
    }


    /**
     * 条件查询+分页
     *
     * @param whereMap
     * @param page
     * @param size
     * @return
     */
    public Page<Converse> findSearch(Map whereMap, int page, int size) {
        Specification<Converse> specification = createSpecification(whereMap);

        PageRequest pageRequest = PageRequest.of(page - 1, size, Sort.by(Sort.Order.desc("createDate")));
        return converseDao.findAll(specification, pageRequest);
    }


    /**
     * 条件查询
     *
     * @param whereMap
     * @return
     */
    public List<Converse> findSearch(Map whereMap) {
        Specification<Converse> specification = createSpecification(whereMap);
        return converseDao.findAll(specification);
    }

    /**
     * 根据ID查询实体
     *
     * @param id
     * @return
     */
    public Converse findById(Long id) {
        return converseDao.findById(id).get();
    }

    /**
     * 增加
     *
     * @param converse
     */
    public void add(Converse converse) {
        converse.setConverse_id(getUniqueId());
        converseDao.save(converse);
    }

    /**
     * 修改
     *
     * @param converse
     */
    public void update(Converse converse) {
        converseDao.save(converse);
    }

    /**
     * 删除
     *
     * @param id
     */
    public void deleteById(Long id) {
        converseDao.deleteById(id);
    }

    /**
     * 动态条件构建
     *
     * @param searchMap
     * @return
     */
    private Specification<Converse> createSpecification(Map searchMap) {

        return new Specification<Converse>() {

            @Override
            public Predicate toPredicate(Root<Converse> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                List<Predicate> predicateList = new ArrayList<Predicate>();
                if (StringUtils.isNotBlank((String) searchMap.get("fromUserId"))) {
                    predicateList.add(cb.equal(root.get("from_user_id").as(Long.class), Long.parseLong((String) searchMap.get("fromUserId"))));
                }
                if (StringUtils.isNotBlank((String) searchMap.get("toUserId"))) {
                    predicateList.add(cb.equal(root.get("to_user_id").as(Long.class), Long.parseLong((String) searchMap.get("toUserId"))));
                }
                if (StringUtils.isNotBlank((String) searchMap.get("converseId"))) {
                    predicateList.add(cb.equal(root.get("converse_id").as(Long.class), Long.parseLong((String) searchMap.get("converseId"))));
                }
                if (StringUtils.isNotBlank((String) searchMap.get("startCreateDate")) && StringUtils.isNotBlank((String) searchMap.get("endCreateDate"))) {
                    predicateList.add(cb.between(root.get("createDate").as(String.class), (String) searchMap.get("startCreateDate"), (String) searchMap.get("endCreateDate")));
                }
                return cb.and(predicateList.toArray(new Predicate[predicateList.size()]));

            }
        };

    }

    public Long addOrGetConverse(Long userId, Long theUserId) {
        Converse exitConverse = converseDao.getByFromUserIdAndToUserId(userId, theUserId);
        if (exitConverse != null) {
            return exitConverse.getConverse_id();
        }
        Converse converse = new Converse();
        converse.setConverse_state(CONVERSE_NORMAL);
        converse.setFrom_user_id(userId);
        converse.setTo_user_id(theUserId);
        converse.setCreateDate(new Date());
        this.add(converse);
        return converse.getConverse_id();
    }

    public List<Converse> getConverseList(Long userId) {
        List<Converse> converseList = converseDao.findByUserId(userId);
        converseList.stream().forEach(converse -> {
            LinkedHashMap<String, Object> toUser = (LinkedHashMap) userClient.findByUserId(converse.getTo_user_id()).getData();
            converse.setNickName((String) toUser.get("nick_name"));
            converse.setUserAvatar((String) toUser.get("avatar"));
            converse.setLastMsg(getLastMsgOfConverse(converse.getFrom_user_id(), converse.getTo_user_id()).getContent());
            converse.setUnReadNum(messageDao.countUnReadMsgByConverseId(converse.getConverse_id()));
        });
        return converseList;
    }

    public Message getLastMsgOfConverse(Long userId, Long theUserId) {
        Converse converse = converseDao.getByFromUserIdAndToUserId(userId, theUserId);
        if (converse == null) {
            return null;
        }
        Message lastMsg = messageService.getLastMsgByConverseId(converse.getConverse_id());
        return lastMsg;
    }

    public void deleteByConverseId(Long converseId) {
        //会话状态修改
        Converse converse = converseDao.findByConverseId(converseId);
        converse.setConverse_state(CONVERSE_DELETE);
        converseDao.save(converse);
        List<Message> messageByConverseId = messageService.getUnDeleteMessageByConverseId(converseId);
        messageByConverseId.stream().forEach(message -> {
            message.setMsg_state(MessageService.MSG_STATE_DELETE + "");
            messageDao.save(message);
        });
    }

    //    @Scheduled(cron = "0/5 * * * * *")
    public void showManger() {
        System.out.println("manager:  " + UserChannelRel.getChannelManager());
    }

    public void batchDelete(List<Long> converseList) {
        converseList.forEach(converseId -> deleteByConverseId(converseId));
    }
}
